package com.dingding.order.core.special.biz.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.http.HttpStatus;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.common.core.base.daox.IBaseDaoX;
import com.dingding.common.core.base.dto.AbstractResponse;
import com.dingding.common.core.base.dto.ResponseEntity;
import com.dingding.common.core.beans.Useraccountdetail;
import com.dingding.common.core.beans.Userdetail;
import com.dingding.common.core.beans.special.Specialuserlogin;
import com.dingding.common.core.beans.special.UserspecialorderT;
import com.dingding.common.core.config.Constants;
import com.dingding.common.core.model.push.PushModel;
import com.dingding.common.core.push.pushmsg.PushData;
import com.dingding.common.core.push.pushmsg.PushMsg;
import com.dingding.common.core.util.DateFormatUtil;
import com.dingding.common.core.util.GetDistanceUtil;
import com.dingding.common.core.util.JSONUtil;
import com.dingding.common.core.util.ToolUtil;
import com.dingding.common.core.util.amap.AmapApi;
import com.dingding.common.core.util.amap.amapDto.GetDistanceDto;
import com.dingding.common.core.util.dto.CalculatDistanceDTO;
import com.dingding.facade.account.user.service.IUserAccountService;
import com.dingding.facade.queue.dto.push.PushRequestDTO;
import com.dingding.facade.queue.enums.ClientType;
import com.dingding.facade.queue.enums.PushType;
import com.dingding.facade.queue.enums.RoleType;
import com.dingding.facade.queue.facade.IQueueFacade;
import com.dingding.facade.user.service.IUserInfoFacade;
import com.dingding.order.code.order.SpecialOrderStatus;
import com.dingding.order.core.pay.biz.IPayNotifyService;
import com.dingding.order.core.pay.biz.pay.IPaymentService;
import com.dingding.order.core.special.biz.ISpecialOrderService;
import com.dingding.order.core.special.dao.ISpecialOrderDao;
import com.dingding.order.core.special.dao.IUserSpecialOrdertDao;
import com.dingding.order.dto.pay.ReqTaxiOneLinePayDTO;
import com.dingding.order.dto.pay.TaxiOrderPayPushDTO;
import com.dingding.order.dto.special.boardingtime.ReqBoardingTime;
import com.dingding.order.dto.special.boardingtime.ResBoardingTime;

/**
 * @Description:
 * @author fengshuonan
 * @date 2016年8月18日 下午2:45:16
 * @version 叮叮搭车
 * @since 2.4
 */
@Component("specialOrderService")
public class SpecialOrderServiceImpl extends AbstractResponse<ResBoardingTime, ReqBoardingTime>
		implements ISpecialOrderService {

	private Logger log = Logger.getLogger(this.getClass());

	/**
	 * 支付操作service
	 */
	@Resource(name = "dingbiPayment")
	private IPaymentService paymentService;
	
	@Resource(name = "specialOrderDao")
	private ISpecialOrderDao specialOrderDao;

	@Resource(name = "userAccountService")
	private IUserAccountService userAccountService;

	@Resource(name = "userInfoService")
	private IUserInfoFacade userInfoFacade;

	@Resource(name = "payNotifyService")
	private IPayNotifyService payNotifyService;

	@Resource(name = "queueService")
	private IQueueFacade queueFacade;
	
	@Resource(name = "baseDaoX")
	private IBaseDaoX baseDaoX;

	@Resource(name = "userSpecialOrdertDao")
	private IUserSpecialOrdertDao userSpecialOrdertDao;
	
	/**
	 * @Description:实时定位，获取专车最快到达时间，并返回附近车主列表
	 * @author fengshuonan
	 * @since 2.4
	 */
	public String boardingTime(String requestDate) {

		ResponseEntity<ResBoardingTime> responseEntity = new ResponseEntity<ResBoardingTime>();
		ReqBoardingTime request = super.parseRequestJson(requestDate);

		// 验证参数是否为空
		if (!super.validateParam(responseEntity, request)) {
			return super.responseBeanToJson(responseEntity);
		}

		// 补全客户端请求参数
		completionParam(request);
		
		// 缓存获取所有车辆的经纬度信息
		List<GetDistanceDto> dtoList = null;
		dtoList = this.specialOrderDao.getAllDriverCarInfos(request.getCurrentCity(),request.getUserRole());

		if (dtoList == null || dtoList.size() == 0) {
			responseEntity.setCode(HttpStatus.SC_OK);
			responseEntity.setErrorMessage("没有附近车辆");
			responseEntity.setPromptMessage("没有附近车辆");
			return super.responseBeanToJson(responseEntity);
		}

		// 获取乘客附近规定千米内的车主
		List<GetDistanceDto> effctDrivers = GetDistanceUtil.getEffectiveDistance(request.getCurrentLongitude(),
				request.getCurrentLatitude(), dtoList, Constants.CUSTOMER_SPECIAL_SCOPE);
		if (effctDrivers == null) {
			responseEntity.setCode(HttpStatus.SC_OK);
			responseEntity.setErrorMessage("没有附近车辆");
			responseEntity.setPromptMessage("没有附近车辆");
			return super.responseBeanToJson(responseEntity);
		}

		// 获取乘客最快上车时间
		int fastestTime = AmapApi.getOriginsToDestinationFastestTime(request.getCurrentLongitude(),
				request.getCurrentLatitude(), effctDrivers);

		ResBoardingTime boardingTime = new ResBoardingTime();
		boardingTime.setBoardingTime(fastestTime);
		boardingTime.setList(effctDrivers);
		responseEntity.setResponseBody(boardingTime);
		return super.responseBeanToJson(responseEntity);
	}

	/**
	 * 
	 * @Title: completionParam 
	 * @Description: 补全实时获取出租车最快到达时间
	 * @param @return    设定文件 
	 * @author YHQ 
	 * @return ReqBoardingTime    返回类型
	 * 
	 */
	public ReqBoardingTime completionParam(ReqBoardingTime request){
		
		// 计算里程与获取城市
		CalculatDistanceDTO calculatDistanceDTO = GetDistanceUtil.getSingleDistance(request.getCurrentLongitude(),
				request.getCurrentLatitude(), request.getCurrentLongitude(),
				request.getCurrentLatitude());
		
		if(ToolUtil.isBlank(request.getCurrentCity())){
			request.setCurrentCity(calculatDistanceDTO.getCityName());
		}
		
		if(request.getUserRole() == null){
			request.setUserRole(2);
		}
		
		return request;
	}
	
	/**
	 * @Description:订单支付后的回调
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean orderPayNotify(String specialOrderId) {

		String telPhone = null;
		
		// 获取订单信息
		UserspecialorderT specialOrderT = this.specialOrderDao.getById(specialOrderId);
		if (specialOrderT == null) {
			log.error("第三方平台支付成功后，更改专车订单状态失败，原因没有获取到当前订单；订单ID：" + specialOrderT);
			return false;
		}
		try {
			// 给司机转账
			this.userAccountService.recharge(specialOrderT.getGrabOrderUserId(), specialOrderT.getTotalMoney());

			// 乘客累计搭乘
			Userdetail passengerDetail = this.userInfoFacade.getUserDetail(specialOrderT.getPlaceOrderUserId());
			passengerDetail.setTotalTake(passengerDetail.getTotalTake().add(specialOrderT.getDistance()));

			// 更新乘客信息
			userInfoFacade.updateUserDetail(passengerDetail);
			
			telPhone = passengerDetail.getTellphone();
			
			//出租车支付成功后添加交易明细
			addTradeDetail(specialOrderT);
			
			if (specialOrderT.getPayMoney().compareTo(new BigDecimal(0)) > 0) { // 叮币扣款
				ReqTaxiOneLinePayDTO reqTaxiOneLinePayDTO = new ReqTaxiOneLinePayDTO();
				reqTaxiOneLinePayDTO.setPassengerId(specialOrderT.getPlaceOrderUserId());
				reqTaxiOneLinePayDTO.setPayMoney(specialOrderT.getPayMoney());
				paymentService.payment(reqTaxiOneLinePayDTO, new ResponseEntity<ReqTaxiOneLinePayDTO>());
			}
			
			// 订单迁移
			specialOrderDao.OrderTempToFormal(specialOrderId);
		} catch (Exception e) {
			log.error("第三方平台支付成功后，更改订单状态失败！订单ID:" + specialOrderId, e);
			return false;
		}

		// 通知推送
		payPush(specialOrderT.getGrabOrderUserId(), specialOrderId,telPhone);

		// 通知推送
		this.payNoticePush(specialOrderT.getGrabOrderUserId(), specialOrderId);

		return true;
	}

	/**
	 * 支付成功后消息推送 订单支付成功后；需要告知车主已经支付成功，此方法由此而来
	 * 
	 * @param driverId
	 *            车主ID
	 * @param orderId
	 *            订单ID
	 * @author fengshuonan
	 * @since V2.4
	 * 
	 */
	public void payPush(String driverId, String orderId,String telPhone) {

		// 根据用户ID(车主)获取别名
		Specialuserlogin userInfo = this.specialOrderDao.getDriverLogin(driverId);
		if (userInfo != null && ToolUtil.isNotBlank(userInfo.getAliasId())) {

			// 创建推送Bean
			PushData pushData = new PushData();
			// 推送序号(时间戳)
			pushData.setRequestNumber(DateFormatUtil.getTimeInMillis().toString());
			// 推送时间
			pushData.setRequestTime(DateFormatUtil.yyyy_MM_dd_HHmmss());
			// 模块
			pushData.setModular("specialPaySuccessPush");

			TaxiOrderPayPushDTO payPushDTO = new TaxiOrderPayPushDTO();
			payPushDTO.setOrderStatus(SpecialOrderStatus.ORDER_OK);
			payPushDTO.setOid(orderId);
			payPushDTO.setPublishType(3);
			payPushDTO.setTelePhone(telPhone);
			// 推送内容
			pushData.setResponseBody(payPushDTO);

			PushRequestDTO pushRequestDTO = new PushRequestDTO();
			pushRequestDTO.setAliasId(userInfo.getAliasId());
			pushRequestDTO.setAlert(PushMsg.PASSENGER_PAY);
			pushRequestDTO.setRoleType(RoleType.Driver);
			pushRequestDTO.setPushContent(JSONUtil.toJSONString(pushData));
			ClientType clientType = null;
			if (userInfo.getClientType().equals("iOS")){ // iOS
				clientType = ClientType.iOS;
			}else if (userInfo.getClientType().equals("Android")){ // Android
				clientType = ClientType.Android;
			}
			pushRequestDTO.setClientType(clientType);
			pushRequestDTO.setPushType(PushType.alert_msgcontent);

			// 添加消息到队列中
			queueFacade.addPushToQueue(JSONUtil.toJSONString(pushRequestDTO));
		}
	}

	/**
	 * 支付成功后通知消息推送
	 * 订单支付成功后；需要告知车主已经支付成功，此方法由此而来
	 * @Title: payNoticePush 
	 * @param driverId 车主ID
	 * @param orderId 订单ID
	 * @author fengshuonan
	 * @since 2.4
	 */
	public void payNoticePush(String driverId, String orderId) {

		// 根据用户ID(车主)获取别名
		Specialuserlogin userInfo = this.specialOrderDao.getDriverLogin(driverId);
		if (userInfo != null && ToolUtil.isNotBlank(userInfo.getAliasId())) {

			// 创建推送Bean
			PushData pushData = new PushData();
			// 推送序号(时间戳)
			pushData.setRequestNumber(DateFormatUtil.getTimeInMillis().toString());
			// 推送时间
			pushData.setRequestTime(DateFormatUtil.yyyy_MM_dd_HHmmss());
			// 模块
			pushData.setModular("newsNoticePush");

			String content = "乘客支付成功，请注意查收！";
			
			// 推送内容
			pushData.setResponseBody(PushModel.noticeModel(1, content, null));

			PushRequestDTO pushRequestDTO = new PushRequestDTO();
			pushRequestDTO.setAliasId(userInfo.getAliasId());
			pushRequestDTO.setAlert(PushMsg.PASSENGER_PAY);
			pushRequestDTO.setRoleType(RoleType.Driver);
			pushRequestDTO.setPushContent(JSONUtil.toJSONString(pushData));
			ClientType clientType = null;
			if (userInfo.getClientType().equals("iOS")){ // iOS
				clientType = ClientType.iOS;
			}else if (userInfo.getClientType().equals("Android")){ // Android
				clientType = ClientType.Android;
			}
			pushRequestDTO.setClientType(clientType);
			pushRequestDTO.setPushType(PushType.msgcontent);

			// 添加消息到队列中
			queueFacade.addPushToQueue(JSONUtil.toJSONString(pushRequestDTO));
		}
	}
	
	/**
	 * @Description:支付成功后添加交易明细
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	private void addTradeDetail(UserspecialorderT specialordert) {
		
		//添加发单的人的交易明细
		Useraccountdetail useraccountdetail = new Useraccountdetail();
		useraccountdetail.setUadId(ToolUtil.getUid());
		useraccountdetail.setUserId(specialordert.getPlaceOrderUserId());
		useraccountdetail.setTradeMoney(specialordert.getTotalMoney());
		useraccountdetail.setTradeType(2);// 交易类型 (1:收入 2: 支出 3:提现 4:取消(已支付)订单退款)
		useraccountdetail.setTradeTime(new Date());
		if(specialordert.getPayMoney() == null){
			specialordert.setPayMoney(new BigDecimal(0));
		}
		useraccountdetail.setActualPaymentMoney(specialordert.getTotalMoney());
		useraccountdetail.setCouponMoney(new BigDecimal(0));
		
		try {
			this.baseDaoX.save(useraccountdetail);
		} catch (Exception e) {
			log.error("出租车单完成后，添加交易明细失败！",e);
		}
		
	}

}
